#include <iostream>
#include <string.h>
using namespace std;

//函数模板和普通函数在一起
//函数模板不允许自动类型转换
//普通函数能够进行自动类型转换
/**
        1 函数模板可以像普通函数一样被重载
        2 c++编译器优先考虑普通函数
        3 如果函数模板可以产生一个更好的匹配，那么选择函数模板
        4 可以通过空模板实参列表的语法限定编译器只通过模板匹配

*/

int Max(int a, int b){
        cout<<"int Max(int a, int b) "<<endl;
        return a > b ? a : b;
}

template<typename T>
T Max(T a, T b){
        cout<<"T Max(T a, T b) "<<endl;
        return a > b ? a : b;
}

template<typename T>
T Max(T a, T b, T c){
        cout<<"T Max(T a, T b, T c) "<<endl;
        return a > b ? a : b;
}

int main(int argc, char const *argv[]){
        int  a = 1;
        int  b = 2;

        cout<<Max(a, b)<<endl; //当函数模板和普通函数都符合调用时,优先选择普通函数
        cout<<Max<>(a,b)<<endl; //若显示使用函数模板,则使用<>类型列表

        cout<<Max(3.0, 4.0)<<endl;//如果函数模板产生更好的匹配 使用函数模板

        cout<<Max(5.0, 6.0, 7.0)<<endl;//重载

        cout<<Max('a', 100)<<endl; //调用普通函数 隐式类型转换

        return 0;
}

/*
函数模板机制结论:
        编译器并不是把函数模板处理成能够处理任意类的函数
        编译器从函数模板通过具体类型产生不同的函数
        编译器会对函数模板进行两次编译
        在声明的地方对模板代码本身进行编译,在调用的地方对参数替换后的代码进行编译
*/
